﻿using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.AspNetCore.Mvc.ExceptionHandling;
using Volo.Abp.Http.Client;
using Volo.Abp;
using CTP.CRM.Core.Localization;
using Volo.Abp.Validation;
using Volo.Abp.Threading;
using Microsoft.AspNetCore.Mvc.Abstractions;
using CTP.CRM.Core.Common.Dto;

namespace CTP.CRM.Core.Filter
{
    public class GlobalExceptionFilter : AbpExceptionFilter
    {
        private enum ErrorType
        {
            ValidationException = 1,
            BusinessException,
            InnerException
        }

        private readonly IStringLocalizer<CtpBasicLocalization> _localizer;

        public GlobalExceptionFilter(IStringLocalizer<CtpBasicLocalization> localizer)
        {
            _localizer = localizer;
        }

        protected override Task HandleAndWrapException(ExceptionContext context)
        {
            if (context.ExceptionHandled)
            {
                Console.WriteLine("异常被提前处理~");
                return Task.CompletedTask;
            }

            string text = 400.ToString();
            ErrorType errorType = ErrorType.InnerException;
            string text2 = "";
            if (context.Exception is AbpValidationException ex)
            {
                errorType = ErrorType.ValidationException;
                text2 = string.Join(',', ex.ValidationErrors.Select((ValidationResult m) => m.ErrorMessage));
                context.Result = new JsonResult(new UnifyResultDto(text, text2, null));
            }
            else if (context.Exception is BusinessException ex2)
            {
                errorType = ErrorType.BusinessException;
                text = (string.IsNullOrEmpty(ex2.Code) ? text : ex2.Code);
                context.Result = new JsonResult(new UnifyResultDto(text, ex2.Message, ex2.Details));
            }
            else if (context.Exception is AbpRemoteCallException ex3)
            {
                if (!string.IsNullOrEmpty(ex3.Message))
                {
                    context.ExceptionHandled = true;
                    return Task.CompletedTask;
                }
            }
            else if (context.Exception is TaskCanceledException ex4)
            {
                if (!string.IsNullOrEmpty(ex4.Message))
                {
                    context.ExceptionHandled = true;
                    return Task.CompletedTask;
                }
            }
            else
            {
                context.Result = new JsonResult(new UnifyResultDto(500.ToString(), _localizer["Http500Messge"], null));
            }

            WriteLog(context, errorType, text2);
            context.ExceptionHandled = true;
            return Task.CompletedTask;
        }

        private void WriteLog(ExceptionContext context, ErrorType errorType, string validationMessage = "")
        {
            HttpRequest httpRequest = context?.HttpContext?.Request;
            switch (errorType)
            {
                case ErrorType.ValidationException:
                    LogHelper.Warn($"\n    |-请求路径：{context.HttpContext.Request.Path}\n    |-执行时间：{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff")}\n    |-校验结果：{validationMessage} ", false);
                    break;
                case ErrorType.BusinessException:
                    LogHelper.Info($"\n    |-请求路径：{httpRequest?.Path}\n    |-报错时间：{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff")}\n    |-请求编号：{httpRequest.Headers["CTP_Request_Code"]}\n    |-请求用户：{httpRequest.Headers["Authorization"]}\n    |-请求参数：{httpRequest.Headers["CTP_Request_Parameter"]}\n    |-业务异常：{context.Exception} ", false);
                    break;
                case ErrorType.InnerException:
                    LogHelper.Error($"\n    |-请求路径：{httpRequest?.Path}\n    |-报错时间：{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff")}\n    |-请求编号：{httpRequest.Headers["CTP_Request_Code"]}\n    |-请求用户：{httpRequest.Headers["Authorization"]}\n    |-请求参数：{httpRequest.Headers["CTP_Request_Parameter"]}\n    |-异常堆栈：{context.Exception} ", true);
                    break;
            }

            if (httpRequest.Headers.Keys.Contains("CTP_Request_Parameter"))
            {
                httpRequest.Headers.Remove("CTP_Request_Parameter");
            }
        }

        protected override bool ShouldHandleException(ExceptionContext context)
        {
            Type type = AsyncHelper.UnwrapTask(context.ActionDescriptor.GetReturnType());
            if (type == typeof(FileStreamResult))
            {
                return true;
            }

            return base.ShouldHandleException(context);
        }
    }
}
